#!/bin/bash
#
#

#
#$Header$
#


########################################################################
#
#PROJECT:      Unified Sessions Manager
#AUTHOR:       Arno-Can Uestuensoez - acueopensource@gmail.com
#MAINTAINER:   Arno-Can Uestuensoez - acueopensource@gmail.com
#SHORT:        ctys
#CALLFULLNAME: Commutate To Your Session
#LICENCE:      Apache-2.0
#VERSION:      01_11_001
#
########################################################################
#
#     Copyright (C) 2007,2008,2010,2011 Arno-Can Uestuensoez (UnifiedSessionsManager.org)
#
#     This program is free software: you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation, either version 3 of the License, or
#     (at your option) any later version.
#
#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#
#DESCRIPTION:
#     A draft split-off from:
#     	www.unifiedsessionsmanager.org
##
########################################################################

_myLIBNAME_base="${BASH_SOURCE}"
_myLIBVERS_base="01.11.018"

shopt -s nullglob
shopt -s extglob


if [ -z "${CTYS_INI}" -a -z "${CTYS_INSTALLER}" ];then
  echo >&2
  echo "${MYCALLNAME}:$LINENO:ERROR:Variable not yet set:CTYS_INI">&2
  echo "${MYCALLNAME}:$LINENO:ERROR:If this is your first-time call just logout and login.">&2
  echo >&2
  echo "${MYCALLNAME}:$LINENO:ERROR:Initialization seems to be missing, variable not set:CTYS_INI">&2
  echo "${MYCALLNAME}:$LINENO:ERROR:Check your installation, see '.bashrc' or '.bashprofile' or '.profile'">&2
  echo "${MYCALLNAME}:$LINENO:ERROR:At least one is required to be loaded.">&2
  echo >&2
  echo "${MYCALLNAME}:$LINENO:ERROR:If already set a PTY may be required, try '-z pty' or '-z 2'.">&2
  echo >&2
  exit 1
fi

#
#Assure X11-start with fork
#
MYSTARTDISPLAY=${DISPLAY}
export MYSTARTDISPLAY
export DISPLAY
#
#Set some common basic definitions.
#

#if not yet initialized, but pre-defined, than set it
if [ -z "${MYLIBPATH}" ];then
    MYLIBPATH=${CTYS_LIBPATH}
fi

#moment of truth, where it is required to be set
if [ ! -d "${MYLIBPATH}" -o ! -e "${MYLIBPATH}/lib/base.sh" ];then
  echo "${MYCALLNAME}:$LINENO:ERROR:Missing:MYLIBPATH=${MYLIBPATH}"
  echo "${MYCALLNAME}:$LINENO:ERROR:Required to point to the root of the"
  echo "${MYCALLNAME}:$LINENO:ERROR:library to be used."
  exit 1
fi

#make it absolute
if [ -n "${MYLIBPATH##/*}" ];then
    cd "${MYLIBPATH}"
    MYLIBPATH=${PWD}
    cd -
fi

MYLANG=${MYLANG:-$LANG}
case ${MYLANG} in
    de*|De*|DE*) MYLANG=de;;
    en*|En*|EN*) MYLANG=en;;
    *)           MYLANG=en;;
esac


MYDOCBASE=${MYDOCBASE:-$MYLIBPATH/doc}
if [ ! -d "${MYDOCBASE}" ];then
    echo "${MYCALLNAME}:$LINENO:ERROR:Missing:MYDOCBASE=${MYDOCBASE}"
    exit 1
fi

if [ -z "${MYMANPATH//:/}" ];then
    MYDOCPATH=${MYDOCPATH:-$MYDOCBASE/$MYLANG}
    case ${MYLANG} in
	de)
	    MYMANPATH=${MYLIBPATH}/doc/de/man:${MYLIBPATH}/doc/en/man
	    ;;
	en)
	    MYMANPATH=${MYLIBPATH}/doc/en/man:${MYLIBPATH}/doc/de/man
	    ;;
	*)
	    MYLANG=en
	    MYMANPATH=${MYLIBPATH}/doc/en/man:${MYLIBPATH}/doc/de/man
	    ;;
    esac
fi

MYDOCPATH=${MYDOCPATH:-$MYDOCBASE/$MYLANG}
if [ ! -d "${MYDOCPATH}" ];then
    echo "${MYCALLNAME}:$LINENO:ERROR:Missing:MYDOCPATH=${MYDOCPATH}"
    exit 1
fi

MYDOCSEARCH=${MYDOCPATH}
#For now
if [ "${MYDOCPATH//\/en/}" == "${MYDOCPATH}" ];then
    MYDOCSEARCH=${MYDOCSEARCH}:${MYDOCBASE}/en
fi
if [ "${MYDOCPATH//\/de/}" == "${MYDOCPATH}" ];then
    MYDOCSEARCH=${MYDOCSEARCH}:${MYDOCBASE}/de
fi


foundmp=;
for mp in ${MYMANPATH//:/ };do
    [ -d "${mp}" ]&&foundmp=1;
done
if [ -z "${foundmp}" ];then
  echo "${MYCALLNAME}:$LINENO:ERROR:Missing:MYMANPATH=${MYMANPATH}"
  exit 1
fi

MYHELPPATH=${MYHELPPATH:-$MYLIBPATH/help/$MYLANG}
if [ ! -d "${MYHELPPATH}" ];then
  echo "${MYCALLNAME}:$LINENO:ERROR:Missing:MYHELPPATH=${MYHELPPATH}"
  exit 1
fi

MYCONFPATH=${MYCONFPATH:-$MYLIBPATH/conf/ctys}
if [ ! -d "${MYCONFPATH}" ];then
  echo "${MYCALLNAME}:$LINENO:ERROR:Missing:MYCONFPATH=${MYCONFPATH}"
  exit 1
fi

MYMACROPATH=${MYMACROPATH:-$MYCONFPATH/macros}
if [ ! -d "${MYMACROPATH}" ];then
  echo "${MYCALLNAME}:$LINENO:ERROR:Missing:MYMACROPATH=${MYMACROPATH}"
  exit 1
fi

MYPKGPATH=${MYPKGPATH:-$MYLIBPATH/plugins}
if [ ! -d "${MYPKGPATH}" ];then
  echo "${MYCALLNAME}:$LINENO:ERROR:Missing:MYPKGPATH=${MYPKGPATH}"
  exit 1
fi

MYADDONSPATH=${MYADDONSPATH:-$MYLIBPATH/addons}
if [ ! -d "${MYADDONSPATH}" ];then
  echo "${MYCALLNAME}:$LINENO:ERROR:Missing:MYADDONSPATH=${MYADDONSPATH}"
  exit 1
fi

MYINSTALLPATH= #Value is assigned in base. Symbolic links are replaced by target

#The only compromise for bootstrap, calling it explicit 
#from anywhere. 
function baseRegisterLib () {
  libManInfoAdd "${_myLIBNAME_base}" "${_myLIBVERS_base}"
}

################################################################
#               Default definitions - 1/2                      #
################################################################
MYLIBEXECPATH=${MYLIBEXECPATH:-`dirname $0`}

MYHOST=`uname -n`

#set for known WMs -> used in GUI functions
MYWM=$(${MYLIBEXECPATH}/getCurWM.sh)

#Basic OS info for variant decisions.
MYOS=${MYOS:-`$MYLIBEXECPATH/getCurOS.sh`}
MYOSREL=${MYOSREL:-`$MYLIBEXECPATH/getCurOSRel.sh`}
MYDIST=${MYDIST:-`$MYLIBEXECPATH/getCurDistribution.sh`}
MYREL=${MYREL:-`$MYLIBEXECPATH/getCurRelease.sh`}
MYARCH=${MYARCH:-`$MYLIBEXECPATH/getCurArch.sh`}

MYUID=$USER
MYGID=`$MYLIBEXECPATH/getCurGID.sh`
MYPID=$$
MYPPID=$PPID

MYACCOUNT=${USER}@${MYHOST}

DATE=`date +"%Y.%m.%d"`
TIME=`date +"%H:%M:%S"`
HOUR=${TIME%%:*};
#DATETIME=`date +"%Y%m%d%H%M%S"`
DATETIME="${DATE//.}${TIME//:}"
DAYOFWEEK=`date +"%u"`


#
#For now 16bit-array, to be used in level-mode or match-mode.
#

#
#levels
#
export      D_UI=$((2#1))
export    D_FLOW=$((2#10))
export     D_UID=$((2#100))
export    D_DATA=$((2#1000))
export   D_MAINT=$((2#10000))
export   D_FRAME=$((2#100000))
export     D_SYS=$((2#1000000))
export    D_STAT=$((2#10000000000000))
export     D_TST=$((2#100000000000000))
export    D_BULK=$((2#1000000000000000))

#
#subsystems
#
export    S_CONF=$((2#1))
export     S_BIN=$((2#10))
export     S_LIB=$((2#100))
export    S_CORE=$((2#1000))
export     S_GEN=$((2#10000))
export     S_CLI=$((2#100000))
export     S_X11=$((2#1000000))
export     S_VNC=$((2#10000000))
export    S_QEMU=$((2#100000000))
export     S_VMW=$((2#1000000000))
export     S_XEN=$((2#10000000000))
export      S_PM=$((2#100000000000))
export     S_KVM=$((2#1000000000000))
export     S_RDP=$((2#10000000000000))
export    S_VBOX=$((2#100000000000000))

#
#ALL4all
#
export     D_ALL=$((16#ffff))

#mode
M=4;

#debug
DBG=0;

#info
INF=2;

#warning
WNG=2;

#Debugging
C_DARGS=;

#file-scope-list
F=0;
FLST=;
I=1;

#print final interface-pre-exec data
#<level>: prints
C_PFEXE=;


###############################################################
#                    Base definitions                          #
################################################################

#FUNCBEG###############################################################
#NAME:
#  fetchDBGArgs
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function fetchDBGArgs () {
    if [ -n "`echo ${*}| sed -n 's/([^)]*)//g;s/-d /1/p'`" ];then
	C_DARGS=`echo " ${*} "| sed -n 's/^.*-d  *\([^ \t)]*\)[ \t)].*$/\1/p'`
	C_DARGS=${C_DARGS%%\%*};
	local i=;
	local KEY=;
	local ARG=;
	for i in ${C_DARGS//[,()]/ };do
	    KEY=`echo ${i%%:*}|tr '[:lower:]' '[:upper:]'`
	    ARG=`echo ${i}|awk -F':' '{print $2}'`
	    case $KEY in
		FILELIST|F)
		    if [ -z "${ARG}" ];then
 			echo "requires numeric value:$KEY">&2
			exit 1;
		    fi
		    FLST=${ARG//[eE][xX][cC][lL][uU][dD][eE]/};
		    if [ "$FLST" != "$ARG" ];then
			I=0;
		    else
			FLST=${FLST//[iI][nN][cC][lL][uU][dD][eE]/};
			if [ "$FLST" != "$ARG" ];then
			    I=1;
			fi
		    fi
                    F=1;
		    ;;
		SUBSYSTEM|S)
		    S=${ARG};
		    if [ -n "${S//[0-9]/}" ];then
			echo "requires numeric value:$KEY">&2
			exit 1;
		    fi
		    ;;
		PATTERN|P)M=1;;
		MIN)M=2;;
		MAX)M=4;;
		WARNING|W)
		    export WNG=${ARG};
		    if [ -n "${WNG//[0-9]/}" ];then
			echo "requires numeric value:$KEY">&2
			exit 1;
		    fi
		    ;;
		INFO|I)
		    export INF=${ARG};
		    if [ -n "${I//[0-9]/}" ];then
			echo "requires numeric value:$KEY">&2
			exit 1;
		    fi
		    ;;
		[0-9]*)
		    DBG=$KEY;
		    if [ -n "${DBG//[0-9]/}" ];then
			echo "requires numeric value:$KEY">&2
			exit 1;
		    fi
		    ;;
		ALL)DBG=$D_ALL;;
		PRINTFINAL|PFIN|PF)
		    export C_PFEXE=${ARG:-0};
		    if [ -n "${C_PFEXE//[0-9]/}" ];then
			echo "requires numeric value:$KEY">&2
			exit 1;
		    fi
		    ;;
		*)
		    echo "DBG:unknown value:$KEY">&2
		    exit 1;
		    ;;
	    esac
	done
	C_DARGS=" -d ${C_DARGS} "
	DARGS=" ${C_DARGS} "
    fi
}
fetchDBGArgs $*

if [ -n "`echo $*| sed -n 's/-y/1/p'`" ];then
    export CTYS_XTERM=0;
fi


#FUNCBEG###############################################################
#NAME:
#  checkBASHversion
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function checkBASHversion () {
  #Check some debug features, for runtime basically,
  #for technical part of development, could be ignored for application, if really neccessary!
  if [ ${BASH_VERSINFO[0]} -lt 3 ];then
    echo "${MYCALLNAME}:${MYUID}@${MYHOST}:$LINENO $BASH_SOURCE:WARNING:Version of BASH should be newer than 3.0 required:${BASH_VERSINFO[*]};" >&2;
    if [ -z "`echo $*| sed -n 's/-f/1/p'`" ];then
      echo "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$LINENO $BASH_SOURCE:INFO:An appropriate version might be installed." >&2;
      echo "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$LINENO $BASH_SOURCE:INFO:For now the mismatch is regarded as minor, though try temporarily the  \"-f\" option." >&2;
      exit 1  
    fi
  fi

  #Some mandatory features like almost full scope of arrays and
  #correct line numbering for debugging is seen as mandatory prerequisite!
  if [ \
       ${BASH_VERSINFO[0]} -lt 2 \
       -o ${BASH_VERSINFO[0]} -lt 2 -a ${BASH_VERSINFO[1]} -lt 6 \
  ];then
    echo "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$LINENO $BASH_SOURCE:ERROR:Version of BASH newer than 2.05 required, current=${BASH_VERSINFO[*]};" >&2;
    exit 1  
  fi
}

checkBASHversion $*

#FUNCBEG###############################################################
#NAME:
#  doDebug
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Returns wheter debug level matches. If some specific
#  actions to be done. E.g. evaluating time-intensive
#  debug actions for tests.
#
#   -> doDebug <subsys> <dbg-level> <line> <file>
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#    0: Debug it.
#    1: No debug.
#  VALUES:
#
#FUNCEND###############################################################
function doDebug  () {
    ((DBG>0))||return 1;
    local s=$1;shift;
    [ -n "${S}" ]&&{ ((S&s))||return 1; }
    local l=$1;shift;
    local L=$1;shift;
    local f=${1%/*/*};f=${1#$f\/};shift;
    if((M&4&&DBG>l));then echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$l:DBG>on">&2;return 0;fi
    if((M&2&&DBG<l));then echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$l:DBG<on">&2;return 0;fi
    if((M&1&&DBG&l));then echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$l:DBG&on">&2;return 0;fi
    return 1;
}



#FUNCBEG###############################################################
#NAME:
#  printDBG
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Prints only when called with more than one option and matches defined 
#  number.
#
#   -> printDBG <subsys> <dbg-level> <line> <file> <message>
#
#  implementation priority: PERFORMANCE
#
#EXAMPLE:
#PARAMETERS:
#OUTPUT:
#  RETURN:
#  VALUES:
#FUNCEND###############################################################
function printDBG {
    local r=$?;
    ((DBG>0))||return $r;
    local s=$1;shift;
    [ -n "${S}" ]&&{ ((S&s))||return $r; }
    local l=$1;shift;
    local L=$1;shift;
    local f=${1%/*/*};f=${1#$f\/};shift;
    ((F^1))&&{
	((M&4&&DBG>l))&&{ echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$s:$l:$*">&2;return $r; }
	((M&2&&DBG<l))&&{ echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$s:$l:$*">&2;return $r; }
	((M&1&&DBG&l))&&{ echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$s:$l:$*">&2;return $r; }
    }||{ [  "$I" == 1 -a "${FLST//$f/}" != "${FLST}" ]&&{
	    ((M&4&&DBG>l))&&{ echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$s:$l:$*">&2;return $r; }
	    ((M&2&&DBG<l))&&{ echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$s:$l:$*">&2;return $r; }
	    ((M&1&&DBG&l))&&{ echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$s:$l:$*">&2;return $r; }
	}
    }||{ [ "$I" == 0 -a "${FLST//$f/}" == "${FLST}" ]&&{
	    ((M&4&&DBG>l))&&{ echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$s:$l:$*">&2;return $r; }
	    ((M&2&&DBG<l))&&{ echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$s:$l:$*">&2;return $r; }
	    ((M&1&&DBG&l))&&{ echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:$s:$l:$*">&2;return $r; }
	}
    }
}


#FUNCBEG###############################################################
#NAME:
#  printERR
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Prints errors
#   -> printERR <line> <fname> <code> <message>
#
#EXAMPLE:
#PARAMETERS:
#OUTPUT:
#  RETURN:
#  VALUES:
#FUNCEND###############################################################
function printERR () {
    local r=$?;
    local L=$1;shift;
    local f=${1%/*/*};f=${1#$f\/};shift;
    if((DBG>0));then 
	if [ "$CTYS_XTERM" == 1  ];then local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:ERROR:$1";
	else local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:\033[31mERROR\033[m:$1";fi
    else
	if [ "$CTYS_XTERM" == 1  ];then local b="${MYCALLNAME}:${MYUID}@${MYHOST}:ERROR:$1";
	else local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:\033[31mERROR\033[m:$1";fi
    fi
    shift;echo -e "$b:$*" >&2;
    return $r;
}



#FUNCBEG###############################################################
#NAME:
#  printWNG
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Prints warnings
#   -> printWNG <warning-level> <line> <fname> <code> <message>
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function printWNG () {
    local r=$?;
    local l=$1;shift;
    ((WNG>l))||return;
    local L=$1;shift;
    local f=${1%/*/*};f=${1#$f\/};shift;
    if((DBG>0));then 
	if [ "$CTYS_XTERM" == 1  ];then local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:WARNING:$1";
	else local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:\033[35mWARNING\033[m:$1";fi
    else
	if [ "$CTYS_XTERM" == 1  ];then local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:WARNING:$1";
	else local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:\033[35mWARNING\033[m:$1";fi
    fi    
    shift;echo -e "$b:$*" >&2;
    return $r;
}




#FUNCBEG###############################################################
#NAME:
#  printINFO
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Prints warnings
#   -> printINFO <info-level> <line> <fname> <code> <message>
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function printINFO () {
    local r=$?;
    local l=$1;shift;
    ((INF>0))||return;
    local L=$1;shift;
    local f=${1%/*/*};f=${1#$f\/};shift;
    local e=$1;shift;
    local o=;
    ((DBG>0))&&o="${f}:";

    (((M&4&&INF>l)||(M&2&&INF<l)||(M&1&&INF&l)))&&{
      ((CTYS_XTERM==1))&&{
         ((F^1))&&{
            echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$o$L:INFO:$e:$*">&2;
	 }||{
            [ \( "$I" == 0 -a "${FLST//$f/}" == "${FLST}" \)  -o  \( "$I" == 1 -a "${FLST//$f/}" != "${FLST}" \) ]&&{
	       echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$o$L:INFO:$e:$*">&2;	
            }
         }
      }||{
	((F^1))&&{
	    echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$o$L:\033[32mINFO\033[m:$e:$*">&2; 
	}||{ 
            [ \( "$I" == 0 -o  "$I" == 1 \) -a "${FLST//$f/}" != "${FLST}" ]&&{
	       echo -e "${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$o$L:\033[32mINFO\033[m:$e:$*">&2;
	    }
	}
      }
    }
    return $r;
}



#FUNCBEG###############################################################
#NAME:
#  printFINALCALL
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Prints final call strings
#   -> printFINALCALL <level> <line> <fname> <title> <exec-or-call-string>
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function printFINALCALL () {
    local r=$?;
    local l=$1;shift;
    [ -n "$C_PFEXE" ]&&((C_PFEXE>=l))||return;
    local L=$1;shift;
    local f=${1%/*/*};f=${1#$f\/};shift;
    local t=${1};shift;
    local a=${*//  / };
    if((DBG>0));then 
	if [ "$CTYS_XTERM" == 1  ];then local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:PRINT:\n$t\n--->\n${a//  / }\n<---";
	else local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:$f:$L:\033[32mPRINT\033[m:\n\033[1m\033[4m$t\033[m\n\033[1m===>\033[m\n${a//  / }\n\033[1m<===\033[m";fi
    else
	if [ "$CTYS_XTERM" == 1  ];then local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:PRINT:\n$t\n--->\n${a//  / }\n<---";
	else local b="${MYCALLNAME}:${MYUID}@${MYHOST}:$$:\033[32mPRINT\033[m:\n\033[1m\033[4m$t\033[m\n\033[1m===>\033[m\n${a//  / }\n\033[1m<===\033[m";fi
    fi
    shift; echo -e "$b" >&2;
    return $r;
}


#FUNCBEG###############################################################
#NAME:
#  callErrOutWrapper
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Fetched the User-ID and Group-UID of primary group,
#  as string in the format:
#
#    <uid>;<guid>
#
#EXAMPLE:
#
#GLOBAL:
#  CTYS_NOCALLWRAPPER
#
#PARAMETERS:
#  $1:    LINENO of caller
#  $2:    BASH_SOURCE of caller
#  $3-*:  The call to be wrapped
#
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function callErrOutWrapper () {
    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:<${@}>"

    local _originLine=$1;shift
    local _originFile=$1;shift
    local _cli=$*
    local _res=0
    printDBG $S_LIB $D_BULK $_originLine "$_originFile" 0 "$FUNCNAME:<${@}>"

    if [ -n "${CTYS_NOCALLWRAPPER}" ];then
	${_cli}
	return $?
    fi

    exec 3>&1
    exec 4>&2
    local _buf=`{ eval "${_cli}"; } 2>&1 1>&3;echo -n "_-_-_$?";`
    printDBG $S_LIB $D_BULK $_originLine "$_originFile" "$FUNCNAME:A-_buf=<${_buf}>"
    _res="${_buf##*_-_-_}"
    if [ -n "${_res//[0-9]/}" ];then
	printERR $LINENO $BASH_SOURCE 1 "${FUNCNAME}:Possible internal error, but seems recoverable, continue:"
	printERR $LINENO $BASH_SOURCE 1 "${FUNCNAME}:=>_buf=<${_buf}>"
	_res=1;
    fi

    _buf="${_buf%_-_-_*}"

    printDBG $S_LIB ${D_BULK} $_originLine "$_originFile" "$FUNCNAME:B-_buf=<${_buf}>"
    exec 3>&-
    exec 4>&-

    echo ${_buf}

    local _rd=;
    [ "$CTYS_XTERM" == 0 ]\
      &&{ [ "$_res" == 0 ]&&_rd="\033[32m OK \033[m"||_rd="\033[31m NOK \033[m"; }\
      ||{ [ "$_res" == 0 ]&&_rd=" OK "||_rd=" NOK "; }

    printDBG $S_LIB ${D_BULK} $_originLine "$_originFile" "$FUNCNAME:_res=<${_rd}>"
    printDBG $S_LIB ${D_SYS} $_originLine "$_originFile" "$FUNCNAME:`setSeverityColor TRY \"call(${_cli})\"` => [ ${_rd} ]"
    return $_res
}



#FUNCBEG###############################################################
#NAME:
#  splitPath
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Lists long search paths(e.g. PATH, LD_LIBRARY_PATH) as one entry 
#  on each line spanning multiple lines.
#
#EXAMPLE:
#
#PARAMETERS:
# $1:  Prefix-String for indention
# $2:  Name of variable
# $3:  colon-seperated path variable
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function splitPath () {
  local _indent=$1;shift
  echo "${1}:${2}"|awk -F":" -v inde=${_indent} '
    { 
      printf("%-"inde-1"s= %s\n",$1,$2);
      for(i=3;i<=NF;i++){
        printf("%"inde+2"s%s\n",":",$i);
      }
    }
  '
}


#FUNCBEG###############################################################
#NAME:
#  splitArgs
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Lists call strings with one option on each line.
#
#  REMARK: 
#   Last option is ambiguous due to suboptions
#   for generic processing, so it could be the
#   first argument.
#
#EXAMPLE:
#
#PARAMETERS:
# $1:  Prefix-String for indention
# $2:  Name of variable
# $3:  colon-seperated path variable
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function splitArgs () {
  local _indent=$1;shift
  local _name=$1;shift

  echo "${_name}:${*}"|sed 's/ --/ |--/g;s/ \(-[^-]\)/ |\1/g;'|awk -F'|' -v inde=${_indent} '
    { 
      printf("%-"inde-1"s",$1);
      for(i=2;i<=NF;i++){
        printf("\n%"inde+2"s%s","",$i);
      }
    }
    END{print "";}
  '|awk -v inde=${_indent} '
    $3==""{ 
        print;
    }
    $3!=""{ 
      printf("%"inde+2"s%s %s","",$1,$2);
      for(i=3;i<=NF;i++){
        printf("\n%"inde+2"s%s","",$i);
      }
    }
    END{print "";}
  '
}






#FUNCBEG###############################################################
#NAME:
#  checkPathElements
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Checks for dengling path elements in search paths seperated by ":"
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function checkPathElements () {
  local PNAME=$1;shift
  local P=;
  for i in `echo ${*}|awk -F':' '{for(i=1;i<=NF;i++)print $i;}'`;do 
    if [ ! -d "${i}" ];then
       RET=1;
       [ -z "$P" ]&&P=1&&printWNG 2 $LINENO $BASH_SOURCE ${RET} "${FUNCNAME}:Invalid search path element in \"${PNAME}\":"
       printWNG 2 $LINENO $BASH_SOURCE ${RET} "${FUNCNAME}: ->${i}"
    fi
  done
  return ${RET}
}

#FUNCBEG###############################################################
#NAME:
#  checkFileListElements
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Checks for existenz and type of a list of files.
#
#EXAMPLE:
#
#PARAMETERS:
#  $@: A list of files-paths with one of the seperators "[: ]"
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function checkFileListElements () {
  local PNAME=$1;shift
  local P
  for i in `echo ${*}|awk -F'[:]' '{for(i=1;i<=NF;i++)print $i;}'`;do 
    if [ ! -f "${i}" ];then
       RET=1;
       [ -z "$P" ]&&P=1&&printWNG 1 $LINENO $BASH_SOURCE ${RET} "${FUNCNAME}:Invalid search file list element in \"${PNAME}\":"
       printWNG 1 $LINENO $BASH_SOURCE ${RET} "${FUNCNAME}: ->${i}"
    fi
  done
  return ${RET}
}




#FUNCBEG###############################################################
#NAME:
#  getRealPathname
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Returns real target for sysmbolic links, else the pathname itself.
#
#  Hardlink is not treated specially.
#
#   $1: Argument is checked for beeing a sysmbolic link, and
#       if so the target will be evaluated and returned,
#       else input is echoed.
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function getRealPathname () {
    local _maxCnt=20;
    local _realPath=${1}
    local _cnt=0

    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "_realPath=${_realPath}"
    while((_cnt<_maxCnt)) ;do    
	if [ -h "${_realPath}" ];then
            _realPath=`ls -l ${1}|awk '{print $NF}'`
        else
	    break;
	fi
	let cnt++;
    done
    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "_realPath=${_realPath}"
    if((_maxCnt==0));then
        ABORT=1;
	printERR $LINENO $BASH_SOURCE ${ABORT} "Path could not be evaluated:${1}"
	printERR $LINENO $BASH_SOURCE ${ABORT} "INFO: Seems to be a circular-chained sysmbolic link"
	printERR $LINENO $BASH_SOURCE ${ABORT} "INFO: Aborted recursion level: ${_maxCnt}"
	gotoHell ${ABORT}
    fi
    echo -n "$_realPath"
}




#FUNCBEG###############################################################
#NAME:
#  gotoHell
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Exit with ignore-check
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function gotoHell () {
  printDBG $S_LIB ${D_FLOW} $LINENO $BASH_SOURCE "Controlled exit($1)"
  [ -n "${C_PRINTINFO}" -a "${C_PRINTINFO}"  != 0 ]&&printLegal;
  [ -z "${IGNORE}" ]&&exit $1
  printWNG 1 $LINENO $BASH_SOURCE ${RET} "${FUNCNAME}:Ignoring exit"
}



#FUNCBEG###############################################################
#NAME:
#  getUserGroup
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function getUserGroup () {
   id $1|sed -n 's/.*gid=[0-9]*(\([^)]*\)).*/\1/p'
}


#FUNCBEG###############################################################
#NAME:
#  checkConsole
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Checks whether running on console.
#
#  Therefore some simplification is assumed due to the specific environment:
#
#   1. ctys supports only SSH connections
#   2  the client and a server could be identified unambiguously by evaluation 
#      the SSH environment variable "SSH_CONNECTION" only, which is on the
#      "originating" client not set.
#
#      The originating client is the very first client, from where the session
#      is started. Any intermediate server, serving as a client in case of 
#      chained sessions, has this variable set.
#
#      But anyhow, it is no longer called from a CONSOLE, thus the criteria 
#      of detection the very-first call is sufficient.

#  
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#    0: IsCONSOLE
#    1: NOT
#  VALUES:
#
#FUNCEND###############################################################
function checkConsole () {
    test -z "${SSH_CONNECTION}"
}


#FUNCBEG###############################################################
#NAME:
#  getPathName
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Due to some wrappers, e.g. "consolehelper" for CentOS/RHEL, the 
#  function evaluates the PATH variable only when run from a console,
#  else hard-coded paths are checked. The paths has to be specifically
#  adapted to the different platforms of course.
#
#  This approach includes support for pre-configured authorization by 
#  usage of PAM modules for specific console-wrappers.1
#  
#EXAMPLE:
#
#PARAMETERS:
#  $1: LINENO of caller
#  $2: BASH_SOURCE of caller
#  $3: ERROR|WARNING|WARNINGEXT
#       ERROR
#        Prints an error message and exits.
#       WARNING  
#        Prints a warning and continues.
#       WARNINGEXT
#        Prints a warning-extended when activated by "-w" and continues.
#  $4: exec callee
#  $5: default path
#
#
#OUTPUT:
#  RETURN:
#    0: Success
#    1: Failure
#  VALUES:
#    pathname
#     With absolute path
#
#FUNCEND###############################################################
function getPathName () {
    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:<$@>"
    local _pname=;
    local _ret=1;

    #if not on console trouble is caused by several console-wrappers
    checkConsole 2>/dev/null >/dev/null
    if [ $? -eq 0 ];then
	printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "running from CONSOLE"
        #try whether access is permitted, else continue with usual business
	_pname=`gwhich $4 2>/dev/null`
	_ret=$?
    fi
#4TEST-4CYGWIN:	    if [ $_ret -ne 0 ];then
    if [ -z "$_pname" ];then
        #try the system specific path
	if [ -n "${5}" ];then
	    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "try \"${5}/${4}\""
	    _pname=`gwhich ${5}/${4} 2>/dev/null`
	    _ret=$?
	else
	    case $3 in
		ERROR)printERR $1 $2 1  "Missing required default path";gotoHell 1;;
		WARNING)printWNG 1 $1 $2 1  "Missing required default path";;
		WARNINGEXT|*)printWNG 2 $1 $2 1  "Missing required default path";;
	    esac
	fi
    fi
    if [ $_ret -ne 0 ];then
    	case $3 in
	    ERROR)printERR $1 $2 1  "Can not evaluate exec-access to \"`setSeverityColor ERR ${4}`\"";gotoHell 1;;
	    WARNING)printWNG 1 $1 $2 1  "Can not evaluate exec-access to \"`setSeverityColor WNG ${4}`\"";;
	    WARNINGEXT|*)printWNG 2 $1 $2 1  "Can not evaluate exec-access to \"`setSeverityColor WNG ${4}`\"";;
	esac
	
    fi
    [ -n "${_pname}" -a $_ret -eq 0 ]&&_disp=`setSeverityColor INF ${_pname}`||_disp=`setSeverityColor WNG "ABSENT(${5}/${4})"`;
    printDBG $S_LIB ${D_SYS} $1 "$2" "$FUNCNAME:`setSeverityColor TRY \"eval(${4})\"` => [ ${_disp} ]"
    if [ $_ret -eq 0 ];then
	echo "$_pname"	
    fi
    return $_ret
}




#FUNCBEG###############################################################
#NAME:
#  setSeverityColor
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Encapsulates the input-string with appropriate escape sequences for
#  colored output. Therefore it is checked whether XTERM is set, and 
#  only than proceeded.
#
#  Operates on STATEs rather than explicitly defined colors. 
#
#  REMARK:
#    Due to performance reasons for parts of common trace-output the 
#    values are hardcoded within the whole module.
#  
#EXAMPLE:
#
#PARAMETERS:
#  $1: ERR|WNG|INF|TRY
#
#      ERR: Error, initally:        red(31)
#      WNG: Warning, initially:     magenta(35)
#      INF: Information, initially: green(32)
#      TRY: Trial input, initially: blue(34)
#
#  $2-*
#OUTPUT:
#  RETURN:
#    0: OK
#    1: NOK
#  VALUES:
#    "<esc-color>$2-*<esc-color-reset>"
#
#FUNCEND###############################################################
function setSeverityColor () {
    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:<$@>"
    local col=$1;shift
    [ "$CTYS_XTERM" != 0 ]&&echo -n -e "$*"||\
    case $col in
	ERR)echo -n -e "\033[31m${*}\033[m";;
	WNG)echo -n -e "\033[35m${*}\033[m";;
	INF)echo -n -e "\033[32m${*}\033[m";;
	TRY)echo -n -e "\033[34m${*}\033[m";;
	*)    echo -n -e "$*";;
    esac
}


#FUNCBEG###############################################################
#NAME:
#  setFontAttrib
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Encapsulates the input-string with appropriate escape sequences for
#  atributes of charachter representation.
#
#  REMARK:
#    Due to performance reasons for parts of common trace-output the 
#    values are hardcoded within the whole module.
#  
#EXAMPLE:
#
#PARAMETERS:
#  $1: BOLD|UNDL|
#      FBLACK|FRED|FGREEN|FYELLOW|FBLUE|FMAGENTA|FCYAN|FWHITE
#      BBLACK|BRED|BGREEN|BYELLOW|BBLUE|BMAGENTA|BCYAN|BWHITE
#      RESET
#  $2-*
#
#OUTPUT:
#  RETURN:
#    0: OK
#    1: NOK
#  VALUES:
#    "<esc-color>$2-*<esc-color-reset>"
#
#FUNCEND###############################################################
function setFontAttrib () {
    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:<$@>"
    local col=$1;shift
    [ "$CTYS_XTERM" != 0 ]&&echo -n -e "$*"||\
    case $col in
	BOLD)echo -n -e "\033[1m${*}\033[m";;
	UNDL)echo -n -e "\033[4m${*}\033[m";;

	FBLACK)echo -n -e "\033[30m${*}\033[m";;
	FRED)echo -n -e "\033[31m${*}\033[m";;
	FGREEN)echo -n -e "\033[32m${*}\033[m";;
	FYELLOW)echo -n -e "\033[33m${*}\033[m";;
	FBLUE)echo -n -e "\033[34m${*}\033[m";;
	FMAGENTA)echo -n -e "\033[35m${*}\033[m";;
	FCYAN)echo -n -e "\033[36m${*}\033[m";;
	FWHITE)echo -n -e "\033[37m${*}\033[m";;

	BBLACK)echo -n -e "\033[40m${*}\033[m";;
	BRED)echo -n -e "\033[41m${*}\033[m";;
	BGREEN)echo -n -e "\033[42m${*}\033[m";;
	BYELLOW)echo -n -e "\033[43m${*}\033[m";;
	BBLUE)echo -n -e "\033[44m${*}\033[m";;
	BMAGENTA)echo -n -e "\033[45m${*}\033[m";;
	BCYAN)echo -n -e "\033[46m${*}\033[m";;
	BWHITE)echo -n -e "\033[47m${*}\033[m";;

        RESET)echo -n -e "\033[m${*}";;

	*)    echo -n -e "$*";;
    esac
}

##############################################################
##############################################################
#FUNCBEG###############################################################
#NAME:
#  removeLeadZeros
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function removeLeadZeros () {
#4TEST:Temp reminder-4del:  echo -e "${1}"|sed -n 's/^0*\([^0].*\)\(.\)$/\1\2/p'
  echo -e -n "${1}"|sed -n 's/^0*\([^0].*\)$/\1/p'
}


#FUNCBEG###############################################################
#NAME:
#  getDateTimeOfInode
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
#  $1:  Inode
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function getDateTimeOfInode () {
  [ -n "$1" -a -e "$1" ]&&{ local x=`ls -l --time-style '+%Y%m%d%H%M%S' $1`;x=${x% *};x=${x##* }; }
  echo -n $x
}


#FUNCBEG###############################################################
#NAME:
#  getMyUGID
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Fetched the User-ID and Group-UID of primary group,
#  as string in the format:
#
#    <uid>;<guid>
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function getMyUGID () {
    local _ugid=`id|sed -n  's/[^u]*uid=[0-9]*(\([^\)]*\)) *gid=[0-9]*(\([^\)]*\)).*/\1;\2/p'`
    echo -n ${_ugid:-;}
}


#FUNCBEG###############################################################
#NAME:
#  getCurTime
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Displays current system time.
#
#EXAMPLE:
#PARAMETERS:
#OUTPUT:
#  RETURN:
#
#  VALUES:
#    <hour>:<minute>:<second>
#
#FUNCEND###############################################################
function getCurTime () {
    date +'%H:%M:%S'
}


#FUNCBEG###############################################################
#NAME:
#  getDiffTime
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Displays the difference between two timestamps.
#
#EXAMPLE:
#PARAMETERS:
#   $1:  subtrahend: <hour>:<minute>:<second>
#  [$2]: subtractor: <hour>:<minute>:<second>
#        When missing current time is used.	
#
#OUTPUT:
#  RETURN:
#    0: OK
#    1: NOK
#  VALUES:
#    difference: $1 - $2 = <hour>:<minute>:<second>
#
#FUNCEND###############################################################
function getDiffTime () {
  local _ct=${2:-$(getCurTime)};
  echo "$1:$_ct"|awk -F':' '{
    end=$4*3600+$5*60+$6
    sta=$1*3600+$2*60+$3

    #assume midnight, and max-diff=24h
    if($4<$1){end=end+24*3600;}

    dif=end-sta

    s=dif%60
    m=((dif-s)/60)%60
    h=((dif-m*60-s)/3600)
    printf("%02d:%02d:%02d",h,m,s);
  }'
}




#FUNCBEG###############################################################
#NAME:
#  getExecArch
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
#  $1:  executable
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function getExecArch () {
  [ -z "$1" ]&&return;
  local _fpath=`gwhich $1`;
  [ -z "$_fpath" ]&&return;
  file "$_fpath"|awk -v myarch="${MYARCH}" '
      /x86-64/{printf("x86_64");exit;}
      /80386/{printf("i386");exit;}
      {printf("%s",myarch);exit;}
  ';
}


#FUNCBEG###############################################################
#NAME:
#  clipWordLine
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Does a simple clipping, but considers "words" to be the break-start.
#
#  Reads stream from stdin.
#
#EXAMPLE:
#
#PARAMETERS:
#  $1:  size of line-entry, includes indent, default=80
#  $2:  indent, any line "1+", default=0
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function clipWordLine () {
    local _size="${1:-80}";
    local _indent="${2:-0}";

    awk -v size="${_size}" -v indent="${_indent}" -f ${_myLIBNAME_miscBASE}/clipWordLine.awk
}



#FUNCBEG###############################################################
#NAME:
#  matchFirstFile
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Matches first file within provided pathlist
#
#EXAMPLE:
#
#PARAMETERS:
#  $1:    file to be found
#  $2-*:  path to be searched
#
#OUTPUT:
#  RETURN:
#    0: OK
#    1: NOK
#  VALUES:
#    PATHNAME of found file, else searched filename
#
#FUNCEND###############################################################
function matchFirstFile () {
    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:ARGV=${*}"
    local _fname=$1;shift
    local _mfname=;
    if [ -f "${_fname}" ];then 
	local _m=1;_mfname=$_fname
    else
	for i in ${*//:/ };do
            _mfname="${i}/$_fname"
	    if [ -f "${_mfname}" ];then local _m=1;break;fi
	done
    fi
    if [ -z "${_m}" ];then 
	printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:no entity present:${_fname}"
	return 0;
    fi
    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:matched:${_mfname}"
    echo $_mfname
    return 0;
}



#FUNCBEG###############################################################
#NAME:
#  matchFirstFileX
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Matches first file within the subtrees of provided pathlist.
#  When no filename provided, all are listed.
#
#EXAMPLE:
#
#PARAMETERS:
#  $1:    file to be found, when empty or "ALL" all are listed.
#  $2-*:  path to be searched
#
#OUTPUT:
#  RETURN:
#    0: OK
#    1: NOK
#  VALUES:
#    PATHNAME of found file, else searched filename
#
#FUNCEND###############################################################
function matchFirstFileX () {
    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:ARGV=${*}"
    local _fname=$1;shift
    local _mfname=;

    if [ -z "${_fname}" -o "${_fname}" == "ALL" ];then 
	if [ -n "${*//:/ }" ];then
	    _mfname=$(find ${*//:/ } -print)
	fi
	echo $_mfname
	return 0;
    fi

    if [ -f "${_fname}" ];then 
	local _m=1;_mfname=$_fname
    else
	if [ -n "${*//:/ }" ];then
	    _mfname=$(find ${*//:/ } -print|awk 'BEGIN{ig=0;}{if(ig!=0){printf("%s",$0);ig=1;}}')
	fi
        if [ -f "${_mfname}" ];then local _m=1;fi
    fi
    if [ -z "${_m}" ];then 
	printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:no entity present:${_fname}"
	return 0;
    fi
    printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "$FUNCNAME:matched:${_mfname}"
    echo $_mfname
    return 0;
}

##############################################################
##############################################################
#FUNCBEG###############################################################
#NAME:
#  checkedSetSUaccess
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Due to required root permissions for some calls impersonation aproach
#  either by sudo or ksu should be used for restricted calls. These calls 
#  might be released for call with root permissions selectively by local 
#  impersonation as root or an preconfigured execution-account.
#  The ctys-tools should be executed as a different user without enhanced
#  privileges.
#
#  When using the root account natively no additional permissions are 
#  required of course.
#
#  For ordinary users without enhnaced privileges one of the following two 
#  approaches could be applied:
#
#  - ksu
#    The preferred approach should be the seamless usage of kerberos, 
#    therefore "ksu" with the configuration file ".k5users" should be used.
#
#    For each user the following entry is required:
#
#     "<users-pricipal> /usr/bin/which /usr/sbin/xm /usr/bin/virsh"
#
#    Where the paths may vary.
#
#    Due to the required few calls to which, xm and/or virsh only ".k5login" 
#    is not required.
#
#    The usage of kerberos is activated as default by the variable
#    "USE_K5USERS". When used in companion with SUDO, then kerberos has priority 
#    if configured.
#
#
#  - sudo
#    Basically the same, but to be handled by local configurations on any 
#    machine.
#
#    The usage of sudo is deactivated as default by the variable
#    "unset USE_SUDO". Could be used in combination with kerberos, but has less 
#    priority when k5users is configured.
#
#
#  REMARKS: The given variables will be set "eval" call, even though could
#           be initially set here, no "export" is applied. 
#           So preferably they should be pre-set, just re-/assigned here.
#
#
#  Any preset variable will be kept, but checked for permissions. When a new 
#  impersonation scan has to be performed, the variable must be cleared before.
#
#  
#EXAMPLE:
#
#  XENCALL="${XENCALL:-ksu -e }"
#  XENCALL="${XENCALL:-sudo }"
#
#  VIRSHCALL="${VIRSHCALL:-ksu -e }"
#  VIRSHCALL="${VIRSHCALL:-sudo }"
#
#GLOBALS:
#  0=>off  1=>on
#
#  USE_KSU=0|1
#  USE_SUDO=0|1
#
#
#PARAMETERS:
#
#  The parameters are order dependant and case sensitive, use keywords literally only.
#
#  [$(+1)]:retry
#        Previous set permissions are ignored, whole procedure is repeated.
#
#  [$(+1)]:norootpreference
#        When not set the root permission is seen as given, when the user is named
#        "root", no actual checks are performed.
#        For some cases the call of this function is the final execution too, thus 
#        setting this ignores the actual user and tries actually to execute the given 
#        trial call in any case.
#
#  [$(+1)]:display1
#        The default behaviour of this call is to suppress any output and just return
#        the execution state.
#        For some rare cases the actual result could be of interest which is echoed on
#        stdout, when set this is displayed on stdout.
#
#  [$(+1)]:display2
#        Similar to display1, but displays stderr.
#
#  $(+1):config-file hint
#        Hint to be presented for source of change.
#
#  $(+1):SU-PREFIX-VAR
#        Prefix to be used for impersonalization, content could be empty, than
#        current USER is tested.
#
#  $(+1):SU-CALLEE-VAR
#        The command to be checked for execution permissions.
#
#  $(+1-*):SU-CALLEE-PARAMS
#        Optional parameters to be tested.
#        This is somewhat tricky. Some commands resquire root permissions only for
#        specific parameters accessing restricted system resources. The remaining 
#        set of parameters are accessible for all users.
#
#        Things become somewhat complicated when the test itself performs a critical 
#        call covering the checked permission. 
#
#        So, it has to be decided from case to case how to proceed.
#
#        For example in case of xm from Xen standard package things are somewhat 
#        simpler to handle by "xm info".
#
#
#OUTPUT:
#  RETURN:
#    0: Success
#    1: Failure
#  VALUES:
#
#FUNCEND###############################################################
function checkedSetSUaccess () {
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:\$@=$@"
    if [ "$1" == retry ];then
	local retry=1;
	shift
    fi

    if [ "$1" == norootpreference ];then
	local norootpref=1;
	shift
    fi

    local disp1=">/dev/null";
    if [ "$1" == display1 ];then
	local disp1=;
	shift
    fi

    local disp2="2>/dev/null";
    if [ "$1" == display2 ];then
	local disp2=;
	shift
    fi

    local _confFile=$1;shift
    local _suPrefix=$1;shift
    if [ -z "${_suPrefix// /}" ];then
	printERR $LINENO $BASH_SOURCE 1  "$FUNCNAME:Internal error, missing parameter"
	gotoHell 1
    fi

    local _suPrefixContent=`eval echo \\\${${_suPrefix}}`

    local _suCallee=$1;shift
    if [ -z "${_suCallee// /}" ];then
	printERR $LINENO $BASH_SOURCE 1  "$FUNCNAME:Internal error, missing parameter"
	gotoHell 1
    fi
    local _suCalleeContent=`eval echo \\\${${_suCallee}}`
    if [ -z "${_suCalleeContent// /}" ];then
	printERR $LINENO $BASH_SOURCE 1  "$FUNCNAME:Internal error, missing content for ${_suCallee}"
	gotoHell 1
    fi
    local _suCalleeArgs=$*

    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_confFile=$_confFile"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suPrefix=$_suPrefix"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suPrefixContent=$_suPrefixContent"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suCallee=$_suCallee"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suCalleeContent=$_suCalleeContent"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suCalleeArgs=$_suCalleeArgs"

    #let this be!
    local _ret=1;

    #if I am root, permissions might not be the question, particularly
    #no entries in k5users and sudoers will be applied.
    #No ID or group membership checked, usage for root-permissions will not be supported.
    if [ "${USER}" == "root" -a -z "$norootpref" ];then
	eval ${_suPrefix}=;
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "permission-detected:USER==root"
	printWNG 2 $LINENO $BASH_SOURCE 1  "No ksu/sudo required, USER==root"
	return 0;
    fi

    #
    #Evaluate permissions actually to use, valid for passwd request too!
    #
    if [ -n "${_suPrefixContent}" -a -z "$retry" ];then
        #do the precheck
	_useGIVEN=1;
        case "${_suPrefixContent}" in
	    */sudo*|sudo*)
                #avoid password reuquest
		if [ "$USE_SUDO" == "1" ];then
		    eval ${_suPrefixContent} ${_suCalleeContent} ${_suCalleeArgs} ${disp2} ${disp1}

		    if [ $? -eq 0 ];then
			_useGIVEN=0;
			printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "permission-detected:GIVEN"
			_ret=0;
		    fi
		fi
		;;
	    */ksu*|ksu*)
		if [ "$USE_K5USERS" == "1" ];then
		    eval ${_suPrefixContent} ${_suCalleeContent} ${_suCalleeArgs} ${disp2} ${disp1}
		    if [ $? -eq 0 ];then
			_useGIVEN=0;
			printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "permission-detected:GIVEN"
			_ret=0;
		    fi
		fi
		;;
	    *)
		_useGIVEN=3;
		printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "unknown-permission-detected:GIVEN-UNKNOWN"
		_ret=1;
		;;
	esac
    else
        #
        #Check call, when an entry is found keep this.
        #So, if there is an entry this will be kept in any case, as more distinguished
        #permission, thus seen as more "valuable".
        #
        #Anyhow, still some pitfalls remain, e.g. when sudo feature for distinguished entries 
        #with specific cli-params are utilized.
        #
        #At least for now the distinction wheter a specific parameter requires root permissions for 
        #it's eventually accessed restricted system resource could be solved by current approach.
        #

        #next priority:Kerberos
        if((_ret!=0));then
            #check kerberos
	    if [ "$USE_K5USERS" == "1" ];then
		printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "try KERBEROS"
		local _check="${KSU} -q -e ${_suCalleeContent} ${_suCalleeArgs}"
		printWNG 2 $LINENO $BASH_SOURCE 0  "**HINT**:if call hangs check native call:${_check} "
		eval callErrOutWrapper $LINENO $BASH_SOURCE ${_check} ${disp1}
		if [ $? -eq 0 ];then
		    eval ${_suPrefix}="\"${_suPrefixContent:-$KSU -q -e }\""
		    _ret=0;
		    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "permission-detected:KERBEROS"
		fi    
	    else
		printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "USE_K5USERS not set, ignore:KERBEROS"
	    fi
	fi

        #next priority:sudo
        if((_ret!=0));then
	    if [ "$USE_SUDO" == "1" ];then
                #check sudoers
		printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "try SUDO"
		local _check="${SUDO} ${_suCalleeContent} ${_suCalleeArgs}"
		printWNG 2 $LINENO $BASH_SOURCE 0  "**HINT**:if call hangs check native call:${_check} "
#		callErrOutWrapper $LINENO $BASH_SOURCE ${_check} ${disp1}
#		callErrOutWrapper $LINENO $BASH_SOURCE eval ${_check} ${disp1}
		eval ${_check} ${disp1}
		if [ $? -eq 0 ];then
		    eval ${_suPrefix}="\"${_suPrefixContent:-$SUDO }\""
		    _ret=0;
		    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "permission-detected:SUDOERS"
		fi
	    else
		printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "USE_SUDO not set, ignore:sudoers"
	    fi    
	fi    

        #check native permissions
        if((_ret!=0));then
	    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "CHECK:${_suCalleeContent} ${_suCalleeArgs} ${disp2} ${disp1}"

	    if [ -n "${_suCalleeContent}" ];then
		eval "${_suCalleeContent} ${_suCalleeArgs} ${disp2} ${disp1}"
#		eval callErrOutWrapper $LINENO $BASH_SOURCE ${_suCalleeContent} ${_suCalleeArgs} ${disp2} ${disp1}
		_ret=$?
		if [ $_ret -eq 0 ];then
		    local _useNATIVE=1;
		    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "permission-detected:NATIVE"
		fi
	    fi
	fi

    fi

    #just for safety, inform of own impersonation capability
    if [ $_ret -eq 0 ];then
        if [ -z "${_suPrefix}" ];then
	    if [ "`id -u`" -eq 0 -a "$USER" != root ];then
		printERR $LINENO $BASH_SOURCE 1  "Oh,..."
		printERR $LINENO $BASH_SOURCE 1  " USER  =${USER}"
		printERR $LINENO $BASH_SOURCE 1  " ${_suCallee}    =${_suCalleeContent}"
		printERR $LINENO $BASH_SOURCE 1  "...you have native root permission as non-root!"
		printERR $LINENO $BASH_SOURCE 1  "Be careful with that axe Eugene!"
		printERR $LINENO $BASH_SOURCE 1  "Anyhow, continue despite assuming that THIS IS an ERROR!"
	    fi
	fi
	return ${_ret}
    fi

    printWNG 2 $LINENO $BASH_SOURCE 1  "NO-ACCESS-GRANTED to USER=$USER for root-permisson to call"
    printWNG 2 $LINENO $BASH_SOURCE 1  "  \"${_suPrefix}=${_suPrefixContent}\""
    printWNG 2 $LINENO $BASH_SOURCE 1  "  \"${_suCallee}=${_suCalleeContent} ${_suCalleeArgs}\""
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "  -> Set ksu/sudo by editing \"/root/.k5users\" and/or \"etc/sudoers\", "
    printWNG 2 $LINENO $BASH_SOURCE 1  "    will be probe-ed and utilized properly."
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "     The general access permission by \"/root/.k5login\" MUST NOT be used!!!"
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  " or"
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "  -> Set ${_suPrefix} to \"ksu -e \" or \"sudo \" and export it(SPACES!!!)."
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  " or"
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "  -> Configure it in this file"
    printWNG 2 $LINENO $BASH_SOURCE 1  "     \"${_confFile}\""
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "Refer to ctys-manual for help and references."
    printWNG 2 $LINENO $BASH_SOURCE 1  "."

    return ${_ret}
}

#FUNCBEG###############################################################
#NAME:
#  setSUaccess
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Sets the given call prefix. No call checks are performed, just the presence 
#  of a authorization method is required.
#
#  This call is foreseen particularly for critical calls such as "halt"
#  which will shutdown the system immediately in any case of success on
#  OpenBSD.
#
#  Thus the access permissions has to be prepared thoroughly for this call 
#  and will be just trusted as given. The following cases are supported.
#
#  - native/root permissions
#  - ksu
#  - sudo
#
#
#  
#EXAMPLE:
#
#  XENCALL="${XENCALL:-ksu -e }"
#  XENCALL="${XENCALL:-sudo }"
#
#  VIRSHCALL="${VIRSHCALL:-ksu -e }"
#  VIRSHCALL="${VIRSHCALL:-sudo }"
#
#GLOBALS:
#  0=>off  1=>on
#
#  USE_KSU=0|1
#  USE_SUDO=0|1
#
#
#PARAMETERS:
#  $1:   config-file hint
#        Hint to be presented for source of change.
#
#  $2:   SU-PREFIX-VAR
#        Prefix to be used for impersonalization, content could be empty, than
#        current USER is tested.
#
#  $3:   SU-CALLEE-VAR
#        The command to be checked for execution permissions.
#
#  $4-*: SU-CALLEE-PARAMS
#        Optional parameters to be tested.
#        This is somewhat tricky. Some commands resquire root permissions only for
#        specific parameters accessing restricted system resources. The remaining 
#        set of parameters are accessible for all users.
#
#        Things become somewhat complicated when the test itself performs a critical 
#        call covering the checked permission. 
#
#        So, it has to be decided from case to case how to proceed.
#
#        For example in case of xm from Xen standard package things are somewhat 
#        simpler to handle by "xm info".
#
#
#OUTPUT:
#  RETURN:
#    0: Success
#    1: Failure
#  VALUES:
#
#FUNCEND###############################################################
function setSUaccess () {
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:\$@=$@"
    local _confFile=$1;shift
    local _suPrefix=$1;shift
    if [ -z "${_suPrefix// /}" ];then
	printERR $LINENO $BASH_SOURCE 1  "$FUNCNAME:Internal error, missing parameter"
	gotoHell 1
    fi

    local _suPrefixContent=`eval echo \\\${${_suPrefix}}`

    local _suCallee=$1;shift
    if [ -z "${_suCallee// /}" ];then
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:No callee provided, not neccessarily an error."
	printWNG 2 $LINENO $BASH_SOURCE 1 "$FUNCNAME:No callee provided, not neccessarily an error."
	return 2
    fi
    local _suCalleeContent=`eval echo \\\${${_suCallee}}`
    if [ -z "${_suCalleeContent// /}" ];then
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:No access value for ${_suCallee}"
	printWNG 2 $LINENO $BASH_SOURCE 1  "$FUNCNAME:No access value for ${_suCallee}"
	return 2
    fi
    local _suCalleeArgs=$*

    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_confFile=$_confFile"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suPrefix=$_suPrefix"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suPrefixContent=$_suPrefixContent"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suCallee=$_suCallee"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suCalleeContent=$_suCalleeContent"
    printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "$FUNCNAME:_suCalleeArgs=$_suCalleeArgs"

    local _ret=1;

    #if I am root, permissions might not be the question, particularly
    #no entries in k5users and sudoers will be applied.
    #No ID or group membership checked, usage for root-permissions will not be supported.
    if [ "${USER}" == "root" ];then
	eval ${_suPrefix}=;
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "permission-detected:USER==root"
	printWNG 2 $LINENO $BASH_SOURCE 1  "No ksu/sudo required, USER==root"
	return 0;
    fi

    if [ -n "${_suPrefixContent}" ];then
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "Already set:${_suPrefixContent}"
	return 0;
    fi

    if [ "$USE_K5USERS" == "1" ];then
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "try KERBEROS"
	eval ${_suPrefix}="\"${_suPrefixContent:-$KSU -e }\""
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "permission-detected:KERBEROS"
	return 0;
    else
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "USE_K5USERS not set, ignore:KERBEROS"
    fi

    if [ "$USE_SUDO" == "1" ];then
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "try SUDO"
	eval ${_suPrefix}="\"${_suPrefixContent:-$SUDO }\""
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "permission-detected:SUDOERS"
 	return 0;
    else
	printDBG $S_LIB ${D_FRAME} $LINENO $BASH_SOURCE "USE_SUDO not set, ignore:sudoers"
    fi    

    if [ "`id -u`" -eq 0 -a "$USER" != root ];then
	printERR $LINENO $BASH_SOURCE 1  " USER  =${USER}"
	printERR $LINENO $BASH_SOURCE 1  " ${_suCallee}    =${_suCalleeContent}"
	printERR $LINENO $BASH_SOURCE 1  "...you have native root permission as non-root!"
	printERR $LINENO $BASH_SOURCE 1  "Anyhow, continue despite assuming that THIS IS an ERROR!"
 	return 0;
    fi

    printWNG 2 $LINENO $BASH_SOURCE 1  "NO-ACCESS-GRANTED to USER=$USER for root-permisson to call"
    printWNG 2 $LINENO $BASH_SOURCE 1  "  \"${_suPrefix}=${_suPrefixContent}\""
    printWNG 2 $LINENO $BASH_SOURCE 1  "  \"${_suCallee}=${_suCalleeContent} ${_suCalleeArgs}\""
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "  -> Set ksu/sudo by editing \"/root/.k5users\" and/or \"etc/sudoers\", "
    printWNG 2 $LINENO $BASH_SOURCE 1  "    will be probe-ed and utilized properly."
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "     The general access permission by \"/root/.k5login\" MUST NOT be used!!!"
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  " or"
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "  -> Set ${_suPrefix} to \"ksu -e \" or \"sudo \" and export it(SPACES!!!)."
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  " or"
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "  -> Configure it in this file"
    printWNG 2 $LINENO $BASH_SOURCE 1  "     \"${_confFile}\""
    printWNG 2 $LINENO $BASH_SOURCE 1  "."
    printWNG 2 $LINENO $BASH_SOURCE 1  "Refer to ctys-manual for help and references."
    printWNG 2 $LINENO $BASH_SOURCE 1  "."

    return ${_ret}
}


###############################################################
###############################################################

MYINSTALLPATH=`getRealPathname ${MYLIBEXECPATHNAME}`
MYINSTALLPATH=${MYINSTALLPATH%/*/*}
printDBG $S_LIB ${D_BULK} $LINENO $BASH_SOURCE "MYINSTALLPATH=${MYINSTALLPATH}"


###############################################################
#                    Append                                   #
###############################################################
if [ -z "$__GUIBASE__" ];then
__GUIBASE__=1;
. ${MYLIBPATH}/lib/libguibase.sh
fi

